First part of file chooser fixes.
authorKristian Rietveld <kris@imendio.com>
Sat, 2 Sep 2006 14:26:12 +0000 (14:26 +0000)
committerKristian Rietveld <kristian@src.gnome.org>
Sat, 2 Sep 2006 14:26:12 +0000 (14:26 +0000)
2006-09-02  Kristian Rietveld  <kris@imendio.com>

First part of file chooser fixes.

* gtk/gtkfilechooserbutton.c (model_add_special): also set the
handle in the model for the desktopdir case.

* gtk/gtkfilechooserdefault.c (shortcuts_add_current_folder): free
volume in case we retrieved it but don't pass it on to insert_path,
(shortcuts_model_create): change the column type for the handles
to pointer instead of GObject so our handle ref counting is not
disturbed,
(show_and_select_paths_finished_loading): don't forget to unref
the dialog.

* gtk/gtkfilesystemunix.c (gtk_file_system_unix_class_init),
(gtk_file_system_unix_init), (gtk_file_system_unix_dispose):
remove pending execute_callbacks_idle during dispose, also
execute all callbacks waiting to be run in the next idle,
(queue_*callback), (execute_callbacks_idle): refactor to maintain
a list of callbacks to call per file system instead of globally,
guard the file system during callback invocation,
(gtk_file_system_unix_get_folder): only add load folder idle if
none has been added yet.

ChangeLog
gtk/gtkfilechooserbutton.c
gtk/gtkfilechooserdefault.c
gtk/gtkfilesystemunix.c

index c972a11bd91645249b5b055f5cb0babc44e0e46f..dd4e88c9cd85a12447f6640b15abfb50a1849a35 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2006-09-02  Kristian Rietveld  <kris@imendio.com>
+
+       First part of file chooser fixes.
+
+       * gtk/gtkfilechooserbutton.c (model_add_special): also set the
+       handle in the model for the desktopdir case.
+
+       * gtk/gtkfilechooserdefault.c (shortcuts_add_current_folder): free
+       volume in case we retrieved it but don't pass it on to insert_path,
+       (shortcuts_model_create): change the column type for the handles
+       to pointer instead of GObject so our handle ref counting is not
+       disturbed,
+       (show_and_select_paths_finished_loading): don't forget to unref
+       the dialog.
+
+       * gtk/gtkfilesystemunix.c (gtk_file_system_unix_class_init),
+       (gtk_file_system_unix_init), (gtk_file_system_unix_dispose):
+       remove pending execute_callbacks_idle during dispose, also
+       execute all callbacks waiting to be run in the next idle,
+       (queue_*callback), (execute_callbacks_idle): refactor to maintain
+       a list of callbacks to call per file system instead of globally,
+       guard the file system during callback invocation,
+       (gtk_file_system_unix_get_folder): only add load folder idle if
+       none has been added yet.
+
 2006-09-01  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkentry.c: Don't unnecessarily reset the im context
index 0aaea8ebc9bd31ada9542868992a53df51599e25..c9d8809e13b8f0f502580c115dc189d314ddc4d1 100644 (file)
@@ -1701,6 +1701,7 @@ model_add_special (GtkFileChooserButton *button)
                          DISPLAY_NAME_COLUMN, _(DESKTOP_DISPLAY_NAME),
                          DATA_COLUMN, path,
                          IS_FOLDER_COLUMN, TRUE,
+                         HANDLE_COLUMN, handle,
                          -1);
 
       button->priv->n_special++;
index e5b6e906025e3618c303da112c3f752a99541089..ff7482527cd7e7e65554b89bdadbd49ce02aee9b 100644 (file)
@@ -1905,7 +1905,11 @@ shortcuts_add_current_folder (GtkFileChooserDefault *impl)
          shortcuts_insert_path (impl, pos, TRUE, volume, NULL, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER);
        }
       else
-       shortcuts_insert_path (impl, pos, FALSE, NULL, impl->current_folder, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER);
+        {
+         shortcuts_insert_path (impl, pos, FALSE, NULL, impl->current_folder, NULL, FALSE, SHORTCUTS_CURRENT_FOLDER);
+         if (volume)
+           gtk_file_system_volume_free (impl->file_system, volume);
+       }
 
       if (base_path)
        gtk_file_path_free (base_path);
@@ -1965,7 +1969,7 @@ shortcuts_model_create (GtkFileChooserDefault *impl)
                                              G_TYPE_BOOLEAN,   /* is the previous column a volume? */
                                              G_TYPE_BOOLEAN,   /* removable */
                                              G_TYPE_BOOLEAN,   /* pixbuf cell visibility */
-                                             G_TYPE_OBJECT);   /* GtkFileSystemHandle */
+                                             G_TYPE_POINTER);   /* GtkFileSystemHandle */
 
   if (impl->file_system)
     {
@@ -5783,6 +5787,7 @@ show_and_select_paths_finished_loading (GtkFileFolder *folder,
 
   browse_files_center_selected_row (data->impl);
 
+  g_object_unref (data->impl);
   gtk_file_paths_free (data->paths);
   g_free (data);
 }
index 1a6ed04b8c2ba077b266bbe8b7c05a049071d7da..64ed3f7db63b7e0eaf4a810ff81894062ab7d0d6 100644 (file)
@@ -75,6 +75,9 @@ struct _GtkFileSystemUnix
 
   GHashTable *handles;
 
+  guint execute_callbacks_idle_id;
+  GSList *callbacks;
+
   guint have_afs : 1;
   guint have_net : 1;
 };
@@ -140,6 +143,7 @@ static const GtkFileInfoType STAT_NEEDED_MASK = (GTK_FILE_INFO_IS_FOLDER |
                                                 GTK_FILE_INFO_ICON);
 
 static void gtk_file_system_unix_iface_init   (GtkFileSystemIface     *iface);
+static void gtk_file_system_unix_dispose      (GObject                *object);
 static void gtk_file_system_unix_finalize     (GObject                *object);
 
 static GSList *             gtk_file_system_unix_list_volumes        (GtkFileSystem     *file_system);
@@ -250,6 +254,8 @@ static GtkFileInfo *create_file_info              (GtkFileFolderUnix *folder_uni
                                                   struct stat *statbuf,
                                                   const char *mime_type);
 
+static gboolean execute_callbacks_idle (gpointer data);
+
 static gboolean fill_in_names     (GtkFileFolderUnix  *folder_unix,
                                   GError            **error);
 static void     fill_in_stats     (GtkFileFolderUnix  *folder_unix);
@@ -300,6 +306,7 @@ gtk_file_system_unix_class_init (GtkFileSystemUnixClass *class)
 {
   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
 
+  gobject_class->dispose = gtk_file_system_unix_dispose;
   gobject_class->finalize = gtk_file_system_unix_finalize;
 }
 
@@ -348,6 +355,9 @@ gtk_file_system_unix_init (GtkFileSystemUnix *system_unix)
     system_unix->have_net = FALSE;
 
   system_unix->handles = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+  system_unix->execute_callbacks_idle_id = 0;
+  system_unix->callbacks = NULL;
 }
 
 static void
@@ -380,6 +390,7 @@ check_handles_at_finalization (GtkFileSystemUnix *system_unix)
 #endif
 
   g_hash_table_destroy (system_unix->handles);
+  system_unix->handles = NULL;
 }
 
 #define GTK_TYPE_FILE_SYSTEM_HANDLE_UNIX (_gtk_file_system_handle_unix_get_type ())
@@ -419,6 +430,24 @@ _gtk_file_system_handle_unix_class_init (GtkFileSystemHandleUnixClass *class)
   gobject_class->finalize = _gtk_file_system_handle_unix_finalize;
 }
 
+static void
+gtk_file_system_unix_dispose (GObject *object)
+{
+  GtkFileSystemUnix *system_unix;
+
+  system_unix = GTK_FILE_SYSTEM_UNIX (object);
+
+  if (system_unix->execute_callbacks_idle_id)
+    {
+      g_source_remove (system_unix->execute_callbacks_idle_id);
+      system_unix->execute_callbacks_idle_id = 0;
+
+      /* call pending callbacks */
+      execute_callbacks_idle (system_unix);
+    }
+
+  G_OBJECT_CLASS (gtk_file_system_unix_parent_class)->dispose (object);
+}
 
 static void
 gtk_file_system_unix_finalize (GObject *object)
@@ -479,7 +508,7 @@ enum callback_types
   CALLBACK_VOLUME_MOUNT
 };
 
-static void queue_callback (enum callback_types type, gpointer data);
+static void queue_callback (GtkFileSystemUnix *system_unix, enum callback_types type, gpointer data);
 
 struct get_info_callback
 {
@@ -522,7 +551,7 @@ queue_get_info_callback (GtkFileSystemGetInfoCallback  callback,
   info->error = error;
   info->data = data;
 
-  queue_callback (CALLBACK_GET_INFO, info);
+  queue_callback (GTK_FILE_SYSTEM_UNIX (handle->file_system), CALLBACK_GET_INFO, info);
 }
 
 
@@ -564,7 +593,7 @@ queue_get_folder_callback (GtkFileSystemGetFolderCallback  callback,
   info->error = error;
   info->data = data;
 
-  queue_callback (CALLBACK_GET_FOLDER, info);
+  queue_callback (GTK_FILE_SYSTEM_UNIX (handle->file_system), CALLBACK_GET_FOLDER, info);
 }
 
 
@@ -609,7 +638,7 @@ queue_create_folder_callback (GtkFileSystemCreateFolderCallback  callback,
   info->error = error;
   info->data = data;
 
-  queue_callback (CALLBACK_CREATE_FOLDER, info);
+  queue_callback (GTK_FILE_SYSTEM_UNIX (handle->file_system), CALLBACK_CREATE_FOLDER, info);
 }
 
 
@@ -651,7 +680,7 @@ queue_volume_mount_callback (GtkFileSystemVolumeMountCallback  callback,
   info->error = error;
   info->data = data;
 
-  queue_callback (CALLBACK_VOLUME_MOUNT, info);
+  queue_callback (GTK_FILE_SYSTEM_UNIX (handle->file_system), CALLBACK_VOLUME_MOUNT, info);
 }
 
 
@@ -669,17 +698,22 @@ struct callback_info
 };
 
 
-static guint execute_callbacks_idle_id = 0;
-static GSList *callbacks = NULL;
 
 static gboolean
 execute_callbacks_idle (gpointer data)
 {
   GSList *l;
+  gboolean unref_file_system = TRUE;
+  GtkFileSystemUnix *system_unix = GTK_FILE_SYSTEM_UNIX (data);
 
   GDK_THREADS_ENTER ();
 
-  for (l = callbacks; l; l = l->next)
+  if (!system_unix->execute_callbacks_idle_id)
+    unref_file_system = FALSE;
+  else
+    g_object_ref (system_unix);
+
+  for (l = system_unix->callbacks; l; l = l->next)
     {
       struct callback_info *info = l->data;
 
@@ -705,10 +739,13 @@ execute_callbacks_idle (gpointer data)
       g_free (info);
     }
 
-  g_slist_free (callbacks);
-  callbacks = NULL;
+  g_slist_free (system_unix->callbacks);
+  system_unix->callbacks = NULL;
+
+  if (unref_file_system)
+    g_object_unref (system_unix);
 
-  execute_callbacks_idle_id = 0;
+  system_unix->execute_callbacks_idle_id = 0;
 
   GDK_THREADS_LEAVE ();
 
@@ -716,7 +753,9 @@ execute_callbacks_idle (gpointer data)
 }
 
 static void
-queue_callback (enum callback_types type, gpointer data)
+queue_callback (GtkFileSystemUnix   *system_unix,
+               enum callback_types  type,
+               gpointer             data)
 {
   struct callback_info *info;
 
@@ -742,10 +781,10 @@ queue_callback (enum callback_types type, gpointer data)
        break;
     }
 
-  callbacks = g_slist_append (callbacks, info);
+  system_unix->callbacks = g_slist_append (system_unix->callbacks, info);
 
-  if (!execute_callbacks_idle_id)
-    execute_callbacks_idle_id = g_idle_add (execute_callbacks_idle, NULL);
+  if (!system_unix->execute_callbacks_idle_id)
+    system_unix->execute_callbacks_idle_id = g_idle_add (execute_callbacks_idle, system_unix);
 }
 
 static GtkFileSystemHandle *
@@ -972,8 +1011,9 @@ gtk_file_system_unix_get_folder (GtkFileSystem                  *file_system,
   queue_get_folder_callback (callback, handle, GTK_FILE_FOLDER (folder_unix), NULL, data);
 
   /* Start loading the folder contents in an idle */
-  folder_unix->load_folder_id =
-    g_idle_add ((GSourceFunc) load_folder, folder_unix);
+  if (!folder_unix->load_folder_id)
+    folder_unix->load_folder_id =
+      g_idle_add ((GSourceFunc) load_folder, folder_unix);
 
   return handle;
 }